#include "Icons.h"
#include <wx/image.h>

#ifdef __WXGTK__
	#include <gtk/gtk.h>
#endif

#ifdef __WXMSW__
	#include <windows.h>  // GDI+
	#include <wx/msw/private.h>
#endif

#include "../../core/Impp.h"

namespace Impp
{

/*
 * IconFile
 */

IconFile::IconFile(const wxBitmap & icon, const wxString & file) :
	icon(icon),
	file(file){}

IconFile::~IconFile(){}

/*
 * ActionIcon
 */

ActionIcon::ActionIcon(const wxString & moduleName, const wxString & actionName, const wxBitmap & icon, const wxString & file) :
	IconFile(icon, file),
	moduleName(moduleName),
	actionName(actionName){}

ActionIcon::~ActionIcon(){}

/*
 * Icons
 */

Icons::Icons() :
	statusImageList(16,16,false,16),
	xstatusImageList(16,16,false,32),
	iconPath(Impp::exemplar()->getPixmapsDir()){


	statusOffline = getBitmapFromFile(wxT("icons/status/offline.png"));
	statusAway = getBitmapFromFile(wxT("icons/status/away.png"));
	statusDnd = getBitmapFromFile(wxT("icons/status/dnd.png"));
	statusInvisible = getBitmapFromFile(wxT("icons/status/invisible.png"));
	statusNA = getBitmapFromFile(wxT("icons/status/na.png"));
	statusOccupied = getBitmapFromFile(wxT("icons/status/occupied.png"));
	statusOnline = getBitmapFromFile(wxT("icons/status/online.png"));
	statusUnknown = getBitmapFromFile(wxT("icons/status/unknown.png"));
	statusFree4Chat = getBitmapFromFile(wxT("icons/status/free4chat.png"));

	noAvatar = getBitmapFromFile(wxT("icons/noavatar.gif"));
	msgNew = getBitmapFromFile(wxT("icons/msg/msg_normal.png"));
	imppIcon = getBitmapFromFile(wxT("icons/main/impp.png"));

	/*
	groupIsExpanded = getBitmap(wxT("icons/buddylist/expand_is.png"));
	groupNotExpanded = getBitmap(wxT("icons/buddylist/expand_not.png"));

	imppIcon = getBitmap(wxT("icons/main/impp.png"));

	groupTogle  = getBitmap(wxT("icons/main/group.png"));
	avasTogle  = getBitmap(wxT("icons/main/avas.png"));

	msgNormal = getBitmap(wxT("icons/msg/msg_normal.png"));
	msgFailed = getBitmap(wxT("icons/msg/msg_failed.png"));
	msgUnknown = getBitmap(wxT("icons/msg/msg_unknown.png"));

	noAvatar = getBitmap(wxT("icons/noavatar.gif"));

	tabLeft = getBitmap(wxT("theme/left.png"));
	tabRight = getBitmap(wxT("theme/right.png"));

	tabCloseNormal = getBitmap(wxT("icons/chat/tab_close_normal.png"));
	tabCloseHover = getBitmap(wxT("icons/chat/tab_close_hover.png"));

	buttonSend = getBitmap(wxT("icons/chat/send.png"));
	buttonHistory = getBitmap(wxT("icons/chat/history.png"));
	buttonUserinfo = getBitmap(wxT("icons/chat/userinfo.png"));

	priority = getBitmap(wxT("icons/main/priority.png"));

	msgNew = msgNormal;

*/
	statusImageList.Add(msgNew);


	for (int i = 0; i < 32; ++i) {

		wxString path = wxT("icons/xstatus/xstatus");
		path << i << wxT(".png");

		wxBitmap bmp = getBitmap(path);
		xstatusImageList.Add(bmp);

		#ifdef __WXMSW__
			xstatusBitmaps.push_back(bmp);
		#endif
	}

}

wxBitmap Icons::getBitmapFromFile(const wxString & relPath){
	wxString path = wxString::Format(wxT("%s/%s"), iconPath.c_str(), relPath.c_str());
	return wxBitmap(path,wxBITMAP_TYPE_ANY);
}


Icons::~Icons()
{
}

wxBitmap Icons::getStatusIcon(const Status & status){

	//Ok we store icons in a map, so wie have not to create it everytime

	//if we have created the icon we can return it:
	std::map<int,int>::iterator iter = imagelistMapping.find(status.getMask());
	if( iter != imagelistMapping.end() ) {

		#ifdef __WXMSW__
			return statusBitmaps.at(iter->second-1);
		#else
			 return statusImageList.GetBitmap(iter->second);
		#endif
	 }


	//the base bitmap:
	wxBitmap base = wxNullBitmap;

	//check if we have a xstatus
	int xstatusNum = status.getExtraStatus();
	//ok if x status is not 0 and a valid number use it:
	if(xstatusNum > 0 && xstatusNum < 33){
		#ifdef __WXMSW__
			base = xstatusBitmaps[xstatusNum-1];
		#else
			base = xstatusImageList.GetBitmap(xstatusNum-1);
		#endif
	}else{
		//so wie have no xstatus -> use normal
		if(status == OFFLINE){
			base = statusOffline;
		}else if(status == UNKNOWN){
			base = statusUnknown;
		}else{
			//can just be online, we could check if it is but
			//we are lazy
			base = statusOnline;
		}
	}

	//we have to create the item
	wxBitmap overlay;

	if(status == AWAY){
		overlay = statusAway;
	}else if(status == FREE4CHAT){
		overlay = statusFree4Chat;
	}else if(status == DND){
		overlay = statusDnd;
	}else if(status == NA){
		overlay = statusNA;
	}else if(status == OCCUPIED){
		overlay = statusOccupied;
	}

	if(!overlay.IsNull()){
		base = composeBitmaps(&base,&overlay,wxSize(16,16));
	}

	if(status == INVISIBLE){
		base = composeBitmaps(&base,&statusInvisible,wxSize(16,16));
	}


	int i = statusImageList.Add(base);
	imagelistMapping.insert(std::pair<int,int>(status.getMask(),i));
	#ifdef __WXMSW__
		statusBitmaps.push_back(base);
	#endif

	return base;
}

wxImageList* Icons::getStatusImageList(){
	return &statusImageList;
}

int Icons::getStatusImageListId(const Status & status){
	//if we have created the icon we can return it:
	std::map<int,int>::iterator iter = imagelistMapping.find(status.getMask());
	if( iter != imagelistMapping.end() ) {
		 return iter->second;
	}
	getStatusIcon(status);
	return getStatusImageListId(status);
}

void Icons::registerActionIcon(const wxString & moduleName, const wxString & actionName, const wxString & iconFile){
	loadedIcons.push_back(new ActionIcon(moduleName,actionName,getBitmapFromFile(iconFile), iconFile));
}

void Icons::registerActionIcon(const wxString & moduleName, const wxString & actionName, const wxBitmap & bmp){
	loadedIcons.push_back(new ActionIcon(moduleName,actionName,bmp, wxEmptyString));
}


wxBitmap Icons::getActionIcon(const wxString & moduleName, const wxString & actionName){
	std::vector<IconFile*>::iterator i;
	for(i = loadedIcons.begin(); i != loadedIcons.end(); i++){
		IconFile* iFile = *i;
		if(ActionIcon* ai = dynamic_cast<ActionIcon*>(iFile)){
			if(ai->moduleName == moduleName && ai->actionName == actionName){
				return ai->icon;
			}
		}
	}
	return wxNullBitmap;
}
wxBitmap Icons::getBitmap(const wxString & iconFile){
	std::vector<IconFile*>::iterator i;
	for(i = loadedIcons.begin(); i != loadedIcons.end(); i++){
		IconFile* iFile = *i;
		if(iFile->file == iconFile){
			return iFile->icon;
		}
	}
	wxBitmap bitmap = getBitmapFromFile(iconFile);
	if(bitmap.IsOk()){
		loadedIcons.push_back(new IconFile(bitmap, iconFile));
	}
	return bitmap;
}

wxBitmap Icons::getSpecialBitmap(const SpecialBitmap & special){
	switch(special){
		case BITMAP_NO_AVATAR:
			return noAvatar;
		case BITMAP_NEW_MSG:
			return msgNew;
		case BITMAP_IMPP_ICON:
			return imppIcon;
	}
	return imppIcon;
}

wxBitmap composeBitmaps(wxBitmap* src1, wxBitmap* src2,const wxSize& size){
	#ifdef __WXGTK__
		wxBitmap ret = src1->GetSubBitmap(wxRect(0, 0, size.x, size.y));
		GdkPixbuf* pixbuf = ret.GetPixbuf();
		gdk_pixbuf_composite(src2->GetPixbuf(),pixbuf,0,0,size.x,size.y,0,0,1.0,1.0,GDK_INTERP_NEAREST,255);
		return ret;
	#endif
	#ifdef __WXM__WXMSW__
		wxBitmap ret = src1->GetSubBitmap(wxRect(0, 0, size.x, size.y));

		MemoryHDC dcSrc1, dcSrc2;
        SelectInHDC a(dcSrc1, GetHbitmapOf(ret));
        SelectInHDC b(dcSrc2, GetHbitmapOf(*src2));

		 BLENDFUNCTION bf;      // structure for alpha blending

		  bf.BlendOp = AC_SRC_OVER;
		  bf.BlendFlags = 0;
		  bf.SourceConstantAlpha = 0xFF;
		  bf.AlphaFormat = AC_SRC_ALPHA;


        AlphaBlend(dcSrc1, 0, 0, 16, 16, (HDC)dcSrc2, 0, 0, 16, 16, bf);

        return ret;
	#endif
	#ifdef __WXMAC_OSX__
		wxBitmap ret = src1->GetSubBitmap(wxRect(0, 0, size.x, size.y));
		wxMemoryDC dc(ret);
		dc.DrawBitmap(*src2, 0, 0, true);
		return ret;
	#endif

}

}
